//////////////////////////////////////////////////
// STUDENT RESEARCH PROJECT						//
// UNIVERSITY OF HAGEN 2012						//
// File:	AnemometerInterfaceRS232.ino		//
// Date:	01.08.2012							//
// Author:	Max Pejs							//
//////////////////////////////////////////////////

//////////////////////////////////////////////////////////
//					System includes						//
//////////////////////////////////////////////////////////
#include <EEPROM.h>
#include <interrupt.h>
#include <io.h>
#include <SoftwareSerial.h>

//////////////////////////////////////////////////////////
//					Project includes					//
//////////////////////////////////////////////////////////
#include "typedef.h"
#include "macro.h"

#include "DataContainer.h"
#include "WeatherDataProcessor.h"
#include "RS232Trace.h"
#include "EepromMemory.h"
#include "Statistic.h"


//////////////////////////////////////////////////////////
//					DEFINITIONS							//
//////////////////////////////////////////////////////////
#define INTERRUPT_CMP_CNT		149
#define RECEIVE_PIN				A0
#define LED_PIN					13
#define RESET_STAT_PIN			4
#define INTERRUPT_NR			0
#define THRESHHOLD				300


//////////////////////////////////////////////////////////
//	Definition and Initialization of global variables	//
//////////////////////////////////////////////////////////
volatile bool syncDone = false;

String recvCmd;
WeatherDataProcessor DataProcessor;
UInt8 recvBit, processingBit;
int value;

UInt16 lastTimerVal = 0, currTimerVal = 0;

//////////////////////////////////////////////////////////
//				interrupt routine						//
//////////////////////////////////////////////////////////
ISR(TIMER2_COMPA_vect) 
{
	cli();      // disable global interrupts
	
	recvBit = analogRead(RECEIVE_PIN) > THRESHHOLD;

	PUSH_BIT(recvBit );

	if(syncDone)
	{
		OCR2A = INTERRUPT_CMP_CNT;
		syncDone = false;
	}

	sei();		// enable global interrupts:
}

//////////////////////////////////////////////////////////
//					setup routine						//
//////////////////////////////////////////////////////////
void setup()
{
	delay(1000);
	TRACE_NL("Start...");
	
	cli();			// disable global interrupts

	/****************/
	/* Set up pins	*/
	/****************/
	pinMode(LED_PIN, OUTPUT);			// LED for signaling current send bit
	pinMode(RESET_STAT_PIN, INPUT);

	digitalWrite(LED_PIN, LOW);

	STATISTIC.SendStatus();
	
	/*****************/
	/* Set up Timer2 */
	/*****************/
	TCCR2A = 0; TCCR2B = 0;		// clear timer settings register

	// Aruino runs at 16 Mhz, so we need to have to get an interrupt after 1.2 ms
	// set compare match register to calculated timer count:
	OCR2A = INTERRUPT_CMP_CNT;

	// turn on CTC mode:
	TCCR2A |= (1 << WGM21);

	// Set CS20 and CS22 bits for 128 prescaler
	TCCR2B |= (1 << CS20); TCCR2B |= (1 << CS22);

	// activate timer compare interrupt for polling receive pin
	// TIMSK2 |= (1 << OCIE2A);

	/****************************/
	/*	Set up comparer			*/
	/****************************/
	ACSR =	(0<<ACD)	|   // Analog Comparator: Enabled
			(1<<ACBG)	|   // Analog Comparator Bandgap Select: AIN0 is applied to the internal reference voltage
			(0<<ACO)	|   // Analog Comparator Output: Off
			(1<<ACI)	|   // Analog Comparator Interrupt Flag: Clear Pending Interrupt
			(1<<ACIE)	|   // Analog Comparator Interrupt: Enabled
			(0<<ACIC)	|   // Analog Comparator Input Capture: Disabled
			(1<<ACIS1)	| (1<ACIS0);   // Analog Comparator Interrupt Mode: Comparator Interrupt on Rising Output Edge

	sei();		// enable global interrupts
}

ISR(ANALOG_COMP_vect )
{
	cli();
	ACSR &= ~(1<<ACIE);

	OCR2A = INTERRUPT_CMP_CNT / 2;
	TCNT2 = 0;
	TIMSK2 |= (1 << OCIE2A);
	
	digitalWrite(LED_PIN, HIGH);
	syncDone = true;
	sei();
}

//////////////////////////////////////////////////////////
//	Activates analog compare interrupt for detecting	//
//	next rising edge									//
////////////////////////////////////////////////////////// 
void GetReadyForNextFrame()
{
	// set analog digital comparator interrupt
	ACSR |= (1<<ACIE);
}

//////////////////////////////////////////////////////////
//			Reset timer interrupt						//
//////////////////////////////////////////////////////////
void StopBitPolling()
{
	cli();
	// clear timer interrupt
	TIMSK2 &= ~(1 << OCIE2A);

	digitalWrite(LED_PIN, LOW);
	sei();
}

//////////////////////////////////////////////////////////
// Reads received serial data and processes them		//
//////////////////////////////////////////////////////////
void ProcessSerialRecv()
{
	recvCmd = READ_STRING();

	if(recvCmd == "stat")
	{
		STATISTIC.SendStatistic();
		return;
	}

	if(recvCmd == "rststat")
	{
		STATISTIC.ResetStatistics();
		return;
	}

	if(recvCmd.startsWith("staton"))
	{
		STATISTIC.SetState(true);
		return;
	}

	if(recvCmd.startsWith("statoff"))
	{
		STATISTIC.SetState(false);
		return;
	}
}

void SendDataToRS232(void)
{
	currTimerVal= millis();
	if( (currTimerVal - lastTimerVal) > TRANSMISSION_DELAY)
	{
		DataProcessor.SendData();
		lastTimerVal = currTimerVal;
	}
}

//////////////////////////////////////////////////////////
//				Arduino Main Routine					//
//////////////////////////////////////////////////////////
void loop()
{
	// Read bit from ringbuffer
	processingBit = POP_BIT();

	// if there no more bits skip bit processing
	if(processingBit != 0xFF)
	{
		DataProcessor.ProcessBit(processingBit);
	}

	if(RS232Trace::GetInstance()->GetSerial()->available() > 0)
	{
		ProcessSerialRecv();
	}

	DataProcessor.SendData();
}